package com.ibo.htlivecamera.socket;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SimpleClient {
    boolean running = false;
    List<SimpleListener> listeners = new ArrayList<>();
    private Socket socket;
    private String name;
    private String host;
    private int port;
    private List<String> supportRates;
    private DataOutputStream dataOutputStream;

    public SimpleClient(String name, List<String> supportRates) {
        this.name = name;
        this.supportRates = supportRates;
    }

    public void setHostAndPort(String host, int port) {
        this.host = host;
        this.port = port;
    }


    public void addListener(SimpleListener simpleListener) {
        this.listeners.add(simpleListener);
    }

    public void start() {
        if (running) return;
        running = true;
        new Thread(SimpleClient.this::handleEvent).start();
    }

    public void stop() {
        if (this.socket != null) {
            try {
                socket.close();
                socket = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void postEvent(SimpleEvent event) {
        if (socket == null || !socket.isConnected()) {
            return;
        }
        if (dataOutputStream == null) return;
        try {
            System.out.println("#######  postEvent " + event.getCommand() + "   " + event.getParam());

            dataOutputStream.writeInt(event.command);
            dataOutputStream.writeUTF(event.param);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void handleEvent() {
        DataInputStream dataInputStream;
        try {
            socket = new Socket();
//            socket.setKeepAlive(true);
            socket.connect(new InetSocketAddress(host, port), 3000);

            dataOutputStream = new DataOutputStream(socket.getOutputStream());
            dataInputStream = new DataInputStream(socket.getInputStream());

            dataOutputStream.writeUTF(name);
            dataOutputStream.writeUTF(StringUtils.join(supportRates, ";"));

            while (socket.isConnected()) {
                int command = dataInputStream.readInt();
                String param = dataInputStream.readUTF();
                fireEvent(new SimpleEvent(command, param));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            running = false;
            fireEvent(new SimpleEvent(SimpleEvent.DISCONNECTED, ""));
        }
    }

    /**
     * 触发事件
     */
    private void fireEvent(SimpleEvent simpleEvent) {
        for (SimpleListener listener : this.listeners) {
            listener.action(simpleEvent);
            if (simpleEvent.consume) break;
        }
    }

    public boolean isConnected() {
        return socket != null && socket.isConnected();
    }
}
